#ifndef __ARG_PARSER_H__
#define __ARG_PARSER_H__

#include <cstring>
#include <cstdio>
#include <cassert>
#include <cstdlib>
#include <string>

#include "vectors.h"

// ================================================================================
// ================================================================================
// VISUALIZATION MODES FOR RADIOSITY
#define NUM_RENDER_MODES 6
enum RENDER_MODE { RENDER_MATERIALS, RENDER_RADIANCE, RENDER_FORM_FACTORS, 
		   RENDER_LIGHTS, RENDER_UNDISTRIBUTED, RENDER_ABSORBED };

class ArgParser {

public:

  ArgParser() { DefaultValues(); }

  ArgParser(int argc, char *argv[]) {
    DefaultValues();

    for (int i = 1; i < argc; i++) {
      if (!strcmp(argv[i],"-cloth")) {
        i++; assert (i < argc); 
        cloth_file = argv[i];
      } else if (!strcmp(argv[i],"-fluid")) {
        i++; assert (i < argc); 
        fluid_file = argv[i];
      } else if (!strcmp(argv[i],"-size")) {
	i++; assert (i < argc); 
	width = height = atoi(argv[i]);
      } else if (!strcmp(argv[i],"-timestep")) {
	i++; assert (i < argc); 
	timestep = atof(argv[i]);
        assert (timestep > 0);
         height = atoi(argv[i]);
      } else if (!strcmp(argv[i],"-background_color")) {
	i++; assert (i < argc);
	double r = atof(argv[i]);
	i++; assert (i < argc);
	double g = atof(argv[i]);
	i++; assert (i < argc);
	double b = atof(argv[i]);
	background_color = Vec3f(r,g,b);

      } else if (!strcmp(argv[i],"-num_form_factor_samples")) {
	i++; assert (i < argc); 
	num_form_factor_samples = atoi(argv[i]);
      } else if (!strcmp(argv[i],"-sphere_rasterization")) {
	i++; assert (i < argc); 
	sphere_horiz = atoi(argv[i]);
         if (sphere_horiz % 2 == 1) sphere_horiz++; 
	i++; assert (i < argc); 
	sphere_vert = atoi(argv[i]);
      } else if (!strcmp(argv[i],"-cylinder_ring_rasterization")) {
	i++; assert (i < argc); 
	cylinder_ring_rasterization = atoi(argv[i]);

      } else if (!strcmp(argv[i],"-num_bounces")) {
	i++; assert (i < argc); 
	num_bounces = atoi(argv[i]);
      } else if (!strcmp(argv[i],"-num_shadow_samples")) {
	i++; assert (i < argc); 
	num_shadow_samples = atoi(argv[i]);
      } else if (!strcmp(argv[i],"-num_antialias_samples")) {
	i++; assert (i < argc); 
	num_antialias_samples = atoi(argv[i]);
      } else if (!strcmp(argv[i],"-ambient_light")) {
	i++; assert (i < argc);
	double r = atof(argv[i]);
	i++; assert (i < argc);
	double g = atof(argv[i]);
	i++; assert (i < argc);
	double b = atof(argv[i]);
	ambient_light = Vec3f(r,g,b);

      } else if (!strcmp(argv[i],"-num_photons_to_shoot")) {
	i++; assert (i < argc);
	num_photons_to_shoot = atoi(argv[i]);
      } else if (!strcmp(argv[i],"-num_photons_to_collect")) {
	i++; assert (i < argc);
	num_photons_to_collect = atoi(argv[i]);
      } else {
	printf ("whoops error with command line argument %d: '%s'\n",i,argv[i]);
	assert(0);
      }
    }
  }

  // ===================================
  // ===================================

  void DefaultValues() {
    width = 500;
    height = 500;
    // BASIC RENDERING PARAMETERS
    input_file = NULL;
    width = 400;
    height = 400;
    background_color = Vec3f(1,1,1);
    raytracing_animation = false;
    radiosity_animation = false;

    timestep = 0.01;
    animate = false;
    // RADIOSITY PARAMETERS
    render_mode = RENDER_MATERIALS;
    interpolate = false;
    wireframe = false;
    num_form_factor_samples = 1;
    sphere_horiz = 8;
    sphere_vert = 6;
    cylinder_ring_rasterization = 20; 

    particles = true;
    velocity = true;
    force = true;
    // RAYTRACING PARAMETERS
    num_bounces = 0;
    num_shadow_samples = 0;
    num_antialias_samples = 1;
    ambient_light = Vec3f(0.1,0.1,0.1);
    intersect_backfacing = false;

    edge_velocity = 0;
    dense_velocity = 0;

    surface = false;
    isosurface = 0.7;

    // PHOTON MAPPING PARAMETERS
    render_photons = true;
    render_kdtree = true;
    num_photons_to_shoot = 10000;
    num_photons_to_collect = 100;
    gather_indirect = false;
    wireframe = false;
    bounding_box = true;
    cubes = false;
    pressure = false;

    gravity = Vec3f(0,-9.8,0);
  }

  // ===================================
  // ===================================
  // REPRESENTATION
  // all public! (no accessors)

  std::string cloth_file;
  std::string fluid_file;
  // BASIC RENDERING PARAMETERS
  char *input_file;
  int width;
  int height;
  Vec3f background_color;
  bool raytracing_animation;
  bool radiosity_animation;

  // animation control
  float timestep;
  bool animate;
  Vec3f gravity;
  // RADIOSITY PARAMETERS
  enum RENDER_MODE render_mode;
  bool interpolate;
  int num_form_factor_samples;
  int sphere_horiz;
  int sphere_vert;
  int cylinder_ring_rasterization;

  // display option toggles 
  // (used by both)
  bool particles;
  bool velocity;
  bool surface;
  bool bounding_box;
  // RAYTRACING PARAMETERS
  int num_bounces;
  int num_shadow_samples;
  int num_antialias_samples;
  Vec3f ambient_light;
  bool intersect_backfacing;

  // used by cloth
  bool force;
  bool wireframe;  
  // PHOTON MAPPING PARAMETERS
  int num_photons_to_shoot;
  int num_photons_to_collect;
  bool render_photons;
  bool render_kdtree;
  bool gather_indirect;

  // used by fluid
  int edge_velocity;
  int dense_velocity;
  float isosurface;
  bool cubes;
  bool pressure;
};

#endif
